package com.titaniume.activitiweb.controller;

import com.titaniume.activitiweb.util.AjaxResponse;
import com.titaniume.activitiweb.util.GlobalConfig;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipInputStream;

/**
 * @ProjectName: activiti7_workflow
 * @Package: com.titaniume.activitiweb.controller
 * @ClassName: ProcessDefinitionController
 * @Author: titan
 * @Description: 定义流程
 * @Date: 2021/11/15 20:38
 * @Version: 1.0
 */
@RestController
@RequestMapping("/processDefinition")
public class ProcessDefinitionController {


    @Autowired
    private RepositoryService repositoryService;

    //添加流程定义通过在线提交BPMN的XML
    @PostMapping(value = "/addDeploymentByString")
    public AjaxResponse addDeploymentByString(@RequestParam("stringBPMN") String stringBPMN,
                                              @RequestParam("deploymentName") String deploymentName) {
        try {
            Deployment deployment = repositoryService.createDeployment()
                    .addString("CreateWithBPMNJS.bpmn", stringBPMN)
                    .name(deploymentName)
                    .deploy();
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    deployment.getId());
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "string部署流程失败",
                    e.toString());
        }
    }


    //添加流程定义通过上传BPMN
    @PostMapping(value = "/uploadStreamAndDeployment")
    public AjaxResponse uploadStreamAndDeployment(@RequestParam("processFile") MultipartFile multipartFile,
                                                  @RequestParam("deploymentName") String deploymentName) {
        try {

            //获取上传文件名
            String originalFilename = multipartFile.getOriginalFilename();
            //获取文件扩展名
            String extension = FilenameUtils.getExtension(originalFilename);
            //获取文件字节流对象
            InputStream inputStream = multipartFile.getInputStream();

            Deployment deployment = null;
            if (extension.equals("zip")) {
                ZipInputStream zipInputStream = new ZipInputStream(inputStream);
                deployment = repositoryService.createDeployment()//初始化部署
                        .addZipInputStream(zipInputStream)
                        .name(deploymentName)
                        .deploy();

            } else {
                deployment = repositoryService.createDeployment()
                        .addInputStream(originalFilename, inputStream)
                        .name(deploymentName)
                        .deploy();

            }
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    deployment.getId() + "" + deployment.getName());
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "添加流程定义通过上传BPMN失败",
                    e.toString());
        }
    }


    //获取流程定义列表
    @GetMapping(value = "/getDefinitions")
    public AjaxResponse getDefinitions() {
        try {

            List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();

            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
            for (ProcessDefinition processDefinition : list) {

                HashMap<String, Object> hashMap = new HashMap<>();

                hashMap.put("name", processDefinition.getName());
                hashMap.put("key", processDefinition.getKey());
                hashMap.put("resourceName", processDefinition.getResourceName());
                hashMap.put("deploymentId", processDefinition.getDeploymentId());
                hashMap.put("version", processDefinition.getVersion());
                listMap.add(hashMap);

            }
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    listMap);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取流程失败",
                    e.toString());
        }
    }


    //获取流程定义XML
    @GetMapping(value = "/getDefinitionXML")
    public void getDefinitionXML(HttpServletResponse response, @RequestParam("deploymentID") String deploymentID
            , @RequestParam("resourceName") String resourceName) {
        try {
            InputStream inputStream = repositoryService.getResourceAsStream(deploymentID, resourceName);
            int available = inputStream.available();
            byte[] bytes = new byte[available];
            response.setContentType("text/xml");
            ServletOutputStream outputStream = response.getOutputStream();
            while (inputStream.read(bytes) != -1) {
                outputStream.write(bytes);
            }
            inputStream.close();
        } catch (Exception e) {
            e.toString();
        }
    }


    //获取流程部署列表
    @GetMapping(value = "/getDeployements")
    public AjaxResponse getDeployements() {
        try {
            List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();
            List<Deployment> list = repositoryService.createDeploymentQuery().list();
            for (Deployment dep : list) {
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("id", dep.getId());
                hashMap.put("name", dep.getName());
                hashMap.put("deployementTime", dep.getDeploymentTime());
                listMap.add(hashMap);
            }
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    listMap);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取流程部署列表失败",
                    e.toString());
        }
    }

    //删除流程定义
    @GetMapping(value = "/delDefinition")
    public AjaxResponse delDefinition(@RequestParam("pdID") String pdID) {
        try {
            repositoryService.deleteDeployment(pdID, true);
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    null);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "删除流程定义失败",
                    e.toString());
        }
    }

    //上传文件
    @PostMapping(value = "/upload")
    public AjaxResponse upload(HttpServletRequest request, @RequestParam("processFile") MultipartFile multipartFile) {
        try {

            if (multipartFile.isEmpty() ) {
                System.out.println("文件为空");
            }
            String originalFilename = multipartFile.getOriginalFilename();
            String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));//后缀名
            String filePath  = "E:\\Code\\activiti7_workflow\\src\\main\\resources\\resources\\bpmn";
            originalFilename =  UUID.randomUUID() + suffixName; //新文件名称
            File file = new File(filePath + originalFilename);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            try {
                multipartFile.transferTo(file);
            } catch (IOException e) {
            }

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    null);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "上传流程文件失败",
                    e.toString());
        }
    }
}
